#include "stdafx.h"
#include "gp_Ax3.h"
#include "gp_Pnt.h"
#include "gp_Ax1.h"
#include "gp_Ax2.h"
#include "gp_Trsf.h"
#include "gp_Vec.h"
#include "gp_Sphere.h"
#include "gp.h"

void gp_Sphere::Coefficients
	(double& A1, double& A2, double& A3, 
	double& B1, double& B2, double& B3, 
	double& C1, double& C2, double& C3,
	double& D) const
{
	// Dans le repere local de la sphere :
	// X*X + Y*Y + Z*Z - radius * radius = 0
	gp_Trsf T;
	T.SetTransformation (pos);
	double T11 = T.Value (1, 1);
	double T12 = T.Value (1, 2);
	double T13 = T.Value (1, 3);
	double T14 = T.Value (1, 4);
	double T21 = T.Value (2, 1);
	double T22 = T.Value (2, 2);
	double T23 = T.Value (2, 3);
	double T24 = T.Value (2, 4);
	double T31 = T.Value (3, 1);
	double T32 = T.Value (3, 2);
	double T33 = T.Value (3, 3);
	double T34 = T.Value (3, 4);
	A1 = T11 * T11 + T21 * T21 + T31 * T31;
	A2 = T12 * T12 + T22 * T22 + T32 * T32;
	A3 = T13 * T13 + T23 * T23 + T33 * T33;
	B1 = T11 * T12 + T21 * T22 + T31 * T32;
	B2 = T11 * T13 + T21 * T23 + T31 * T33;
	B3 = T12 * T13 + T22 * T23 + T32 * T33;
	C1 = T11 * T14 + T21 * T24 + T31 * T34;
	C2 = T12 * T14 + T22 * T24 + T32 * T34;
	C3 = T13 * T14 + T23 * T24 + T33 * T34;
	D  = T14 * T14 + T24 * T24 + T34 * T34 - radius * radius;
}

void gp_Sphere::Mirror (const gp_Pnt& P)
{ pos.Mirror (P); }

gp_Sphere gp_Sphere::Mirrored (const gp_Pnt& P) const
{
	gp_Sphere C = *this;
	C.pos.Mirror (P);
	return C;
}

void gp_Sphere::Mirror (const gp_Ax1& A1)
{ pos.Mirror (A1); }

gp_Sphere gp_Sphere::Mirrored (const gp_Ax1& A1) const
{
	gp_Sphere C = *this;
	C.pos.Mirror (A1);
	return C;
}

void gp_Sphere::Mirror (const gp_Ax2& A2)
{ pos.Mirror (A2); }

gp_Sphere gp_Sphere::Mirrored (const gp_Ax2& A2) const
{
	gp_Sphere C = *this;
	C.pos.Mirror (A2);
	return C;
}

 gp_Sphere::gp_Sphere () : radius (DBL_MAX)
{ }

 gp_Sphere::gp_Sphere (const gp_Ax3& A3,
			     const double Radius) :
			     pos (A3),
			     radius (Radius)
{
	 Standard_ConstructionError_Raise_if(Radius < 0.0, "");
}

 void gp_Sphere::SetLocation (const gp_Pnt& Loc)
{ pos.SetLocation (Loc); }

 void gp_Sphere::SetPosition (const gp_Ax3& A3)
{ pos = A3; }

 void gp_Sphere::SetRadius (const double R)
{
	Standard_ConstructionError_Raise_if(R < 0.0, "");
  radius = R;
}

 double gp_Sphere::Area () const
{ return 4.0 * M_PI * radius * radius; }

 void gp_Sphere::UReverse()
{ pos.YReverse(); }

 void gp_Sphere::VReverse()
{ pos.ZReverse(); }

 bool gp_Sphere::Direct() const
{ return pos.Direct(); }

 const gp_Pnt& gp_Sphere::Location () const
{ return pos.Location(); }

 const gp_Ax3& gp_Sphere::Position () const
{ return pos; }

 double gp_Sphere::Radius () const
{ return radius; }

 double gp_Sphere::Volume () const
{ return (4.0 * M_PI * radius * radius * radius) / 3.0; }

 gp_Ax1 gp_Sphere::XAxis () const
{ return gp_Ax1(pos.Location(), pos.XDirection()); }

 gp_Ax1 gp_Sphere::YAxis () const
{ return gp_Ax1(pos.Location(), pos.YDirection()); }

 void gp_Sphere::Rotate (const gp_Ax1& A1,
			       const double Ang)
{ pos.Rotate (A1, Ang); }

 gp_Sphere gp_Sphere::Rotated (const gp_Ax1& A1,
				     const double Ang) const
{
  gp_Sphere C = *this;
  C.pos.Rotate (A1, Ang);
  return C;
}

 void gp_Sphere::Scale (const gp_Pnt& P,
			      const double S)
{
  pos.Scale (P, S);      
  radius *= S;
  if (radius < 0) radius = - radius;
}

 gp_Sphere gp_Sphere::Scaled (const gp_Pnt& P,
				    const double S) const
{
  gp_Sphere C = *this;
  C.pos.Scale (P, S);
  C.radius *= S;
  if (C.radius < 0) C.radius = - C.radius;
  return C;
}

 void gp_Sphere::Transform (const gp_Trsf& T)
{
  pos.Transform (T);
  radius *= T.ScaleFactor();
  if (radius < 0) radius = - radius;
}

 gp_Sphere gp_Sphere::Transformed (const gp_Trsf& T) const
{
  gp_Sphere C = *this;
  C.pos.Transform (T);
  C.radius *= T.ScaleFactor();
  if (C.radius < 0) C.radius = - C.radius;
  return C;
}

 void gp_Sphere::Translate (const gp_Vec& V)
{ pos.Translate (V); }

 gp_Sphere gp_Sphere::Translated (const gp_Vec& V) const
{
  gp_Sphere C = *this;
  C.pos.Translate (V);
  return C;
}

 void gp_Sphere::Translate (const gp_Pnt& P1,
				  const gp_Pnt& P2)
{ pos.Translate (P1, P2); }

 gp_Sphere gp_Sphere::Translated (const gp_Pnt& P1,
					const gp_Pnt& P2) const
{
  gp_Sphere C = *this;
  C.pos.Translate (P1, P2);
  return C;
}

